using System;
using System.Threading;

namespace Gadgeteer.Interfaces.Fakes.Framework
{
    public abstract class ThreadAction : Disposable
    {
        private bool run;
        protected bool Running { get { return run; } }

        private readonly string threadName;
        public string Name { get { return threadName; } }

        private readonly Object syncRootAct = new Object();
        protected Object SyncRootAct { get { return syncRootAct; } }
        private Thread thread;

        protected ThreadAction(string threadName)
        {
            this.threadName = threadName;
        }

        protected void Start()
        {
            if (thread == null)
            {
                thread = new Thread(Run);
#if NOT_NET_MF
            thread.Name = threadName;
#endif
                run = true;

                InitializeThread();

                thread.Start();
            }
        }

        protected virtual void InitializeThread()
        {
        }

        protected abstract bool ActionRequired();

        protected abstract void Act();

        private void Run()
        {
            while (run)
            {
                if (ActionRequired())
                {
                    lock (syncRootAct)
                    {
                        if (run && ActionRequired())
                        {
                            Act();
                        }
                    }
                }
                else
                {
                    Thread.Sleep(40);
                }
            }
        }

        protected override void DisposeManaged()
        {
            run = false;
            if (thread != null)
            {
                thread.Abort();
                thread = null;
            }
        }
    }
}
